package lk;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;

import lk.Main.CountingHashMap;

public class SpecialVacancyAlgo {
//	PriorityQueue<Employee> employeeList = new PriorityQueue<Employee>();
	ArrayList<Employee> allEmployeeList = new ArrayList<Employee>();
	ArrayList<Employee> eligibleEmployeeList = new ArrayList<Employee>();
	ArrayList<Employee> noRequestEmployees = new ArrayList<Employee>();
	ArrayList<Employee> moreThan5AndNoRequestEmployees = new ArrayList<Employee>();
	ArrayList<Employee> specialEmployeeList = new ArrayList<Employee>();
	
	
	CountingHashMap eligibleLocations   = new CountingHashMap();
	CountingHashMap specialLocations   = new CountingHashMap();
	
	
	BasicEmployee employees[];
	Integer[] locationArray;
	ArrayList<BasicEmployee> noChoiceEmployee = new ArrayList<BasicEmployee>();
	int employeeCount;
	Connection con = null;
	public final static int NO_LOCATION_REQUESTED = -2;
	public final static int LOCATION_NOT_IN_VACANCY_LIST = -1;
	
	public final static int REQUEST_1 = 1;
	public final static int REQUEST_2 = 2;
	public final static int REQUEST_3 = 3;
	public final static int CURRENT_LOCATION = 0;
	public final static int NO_LOCATION = 4;
	public final static int NO_ASSIGNMENT = 9;
	
	public static void main(String[] args) {
		SpecialVacancyAlgo m = new SpecialVacancyAlgo();
		m.getSol();
	}	
	
	public void getSol() {
		loadAllEmployees(); // loads allEmployee arrayLisy
		filterEmployees();
		convertToLightWeightDataStructures();
		//algorithmBackoff();
		//algorithmNaive();
		algorithmMaximumRequest1();
		distributeLocationsOfSpecialListInNaiveWay();
	  	evaluateAndOutputResults(employees);
	  	weightSpecialList();
		
	    Integer[] assignments = new Integer[employees.length];
	 	long tStart = System.currentTimeMillis();
	
		long tEnd = System.currentTimeMillis();
		long tDelta = tEnd - tStart;
		double elapsedSeconds = tDelta / 1000.0;		
	}
	
	public void loadAllEmployees() {
		ResultSet rs = null;
		try {
			con = DriverManager
					.getConnection(
							"jdbc:mysql://localhost:3306/GOV_TRANSFER?useUnicode=true&characterEncoding=utf-8",
							"root", "root");
			if (!con.isClosed()) {
				System.out
						.println("Successfully connected to reading Database ");
				Statement readStmt = (Statement) con.createStatement();
				String sql = "select * from GOV_TRANSFER.TRANSFERS_PMAS_2";

				rs = readStmt.executeQuery(sql);
				if (rs != null) {
					int count = 0;
					while (rs.next()) {
						String employeeNo = rs.getString("employeeNo");
						int currentServicePeriod = rs
								.getInt("currentServicePeriod");
						int totalServicePeriod = rs
								.getInt("totalServicePeriod");
						int currentLocationServicePeriod = rs
								.getInt("currentPlaceServicePeriod");
						String request1 = rs.getString("request1").trim();
						String request2 = rs.getString("request2").trim();
						String request3 = rs.getString("request3").trim();
						String currentLocation = rs
								.getString("currentLocation").trim();
						String oldAssignment = rs.getString(
								"finalTansferResult").trim();

						Employee e = new Employee(employeeNo,
								currentServicePeriod, totalServicePeriod,
								currentLocationServicePeriod, request1.trim(),
								request2.trim(), request3.trim(),
								currentLocation.trim(), oldAssignment);
						allEmployeeList.add(e);
					}
				}

			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	public void filterEmployees() {
		for (Employee e : allEmployeeList) {
			String request1 = e.getRequest1();
			String request2 = e.getRequest2();
			String request3 = e.getRequest3();
			String currentLocation = e.getCurrentLocation();
			int currentLocationServicePeriod = e.getCurrentLocationServicePeriod();

			if (currentLocationServicePeriod < 5
					&& (("".equals(request1) && "".equals(request2) && ""
							.equals(request3)) || (currentLocation.trim().equals(request1.trim())))) {
				noRequestEmployees.add(e);
			} else if (currentLocationServicePeriod >= 5
					&& (("".equals(request1.trim())
							&& "".equals(request2.trim()) && "".equals(request3.trim())))) {
				moreThan5AndNoRequestEmployees.add(e);                  
				eligibleLocations.add(e.getCurrentLocation());              // These employees vacate their places
			} else if (currentLocationServicePeriod < 5) {					
				specialEmployeeList.add(e);
				specialLocations.add(e.currentLocation);				  
			} else {
				eligibleEmployeeList.add(e);
				eligibleLocations.add(e.getCurrentLocation());
			}

		}
		Collections.sort(eligibleEmployeeList);	
		Collections.sort(specialEmployeeList);		
	}
	
	public void convertToLightWeightDataStructures() {
		int i =0;
		locationArray = new Integer[eligibleLocations.size()];
		for(String loc : eligibleLocations.keySet()){
			locationArray[i] = eligibleLocations.get(loc);
		    ++i;
		}
		
		i= 0;
		if(eligibleEmployeeList.size() > 0){
			employees = new BasicEmployee[eligibleEmployeeList.size()];
			int j =0 ;
			for (Employee e : eligibleEmployeeList) {
					
				employees[j] = new BasicEmployee(j,e.getEmployeeNo(),
						getLocationId(e.getRequest1()),
							getLocationId(e.getRequest2()),
								getLocationId(e.getRequest3()),
										getLocationId(e.getCurrentLocation() ));
				
				normalizeUnrequestedLocatons(employees[j]);
				++j;
			}
		}
		
				
	}
	
	public void algorithmBackoff(){
		for (int i = 0; i < employees.length; i++) {   
	  		  
			 
		   if(employees[i].getRequest1() != -1 && locationArray[employees[i].getRequest1()] > 0){
  			   employees[i].setAssignedLocation(REQUEST_1);
  			   --locationArray[employees[i].getRequest1()];
  			    continue;
  		   }else  if ( trySpecialList(employees[i],REQUEST_1,employees[i].getRequest1(),i)){
	  			 continue;
  		   }  
  		   
  		   if( employees[i].getRequest2() != -1 && locationArray[employees[i].getRequest2()] < 1){ // Remove -1 checking and ut in below
   			  if( employees[i].getRequest2() != -1 && backOffAtGivenRequestForAll(i,2)){ // As request 2 does not have vacancies check whether someone above can sacrifice request 1 and move on with request 2 
  		    			continue;
  				} 		
   		   } else if(employees[i].getRequest2() != -1 && locationArray[employees[i].getRequest2()] > 0) {
   			   	employees[i].setAssignedLocation(REQUEST_2); 
 				 --	locationArray[employees[i].getRequest2()];
 				 	continue;
   		   }else if ( trySpecialList(employees[i],REQUEST_2,employees[i].getRequest2(),i)){
	    		 continue;
		   }
  		   
  		   
  		   
  		  if(employees[i].getRequest3() != -1 && locationArray[employees[i].getRequest3()] < 1){
   			  if(employees[i].getRequest3() != -1 &&  backOffAtGivenRequestForAll(i,3)){ // As request 3 does not have vacancies check whether someone above can sacrifice request 2 and move on with request 3
  				/*   employees[i].setAssignedLocation(3); 
  					 --	locationArray[employees[i].getRequest3()];*/
  					continue;
  				} 		
   		   }else if(employees[i].getRequest3() != -1 && locationArray[employees[i].getRequest3()] > 0) {
   			   employees[i].setAssignedLocation(REQUEST_3); 
 				 --	locationArray[employees[i].getRequest3()];
 				 continue;
   		   }else if (trySpecialList(employees[i],REQUEST_3,employees[i].getRequest3(),i)){
	  			 continue;
		   } 
  		   
  		 if(employees[i].getCurrentLocation() != -1 && locationArray[employees[i].getCurrentLocation()] < 1){
  			  if( backOffAtGivenRequestForAll(i,0)){ // As current location  does not have vacancies check whether someone above can sacrifice request 3 and move on with current
 				 /*  employees[i].setAssignedLocation(0); 
 					 --	locationArray[employees[i].getCurrentLocation()];*/
 					 continue;
 				}  		
  		   }else if(employees[i].getCurrentLocation() != -1 && locationArray[employees[i].getCurrentLocation()] > 0) {
  			   employees[i].setAssignedLocation(0); 
 				 --	locationArray[employees[i].getCurrentLocation()];
 				 continue;
  		   }  			 
  		 
  		   
  		  employees[i].setAssignedLocation(4);
  		  
  			  
  	   }
  	   
  
	}
	
	
	   public void algorithmNaive(){
		 	  
		 	  
	 	   for (int i = 0; i < employees.length; i++) { 
	 		   
	 		   if(employees[i].getRequest1() != LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getRequest1()] > 0){
	 			   employees[i].setAssignedLocation(1);
	 			   --locationArray[employees[i].getRequest1()];
	 		   }else  if ( trySpecialList(employees[i],REQUEST_1,employees[i].getRequest1(),i)){
		  			 continue;
	  		   }else if(employees[i].getRequest2() != -1 && locationArray[employees[i].getRequest2()] > 0){
	 			   employees[i].setAssignedLocation(2); 
	 			   --locationArray[employees[i].getRequest2()];	 					 			
	 		   }else if ( trySpecialList(employees[i],REQUEST_2,employees[i].getRequest2(),i)){
		    		 continue;
			   }else if(employees[i].getRequest3() != -1 && locationArray[employees[i].getRequest3()] > 0){
	 			   employees[i].setAssignedLocation(3); 
	 			   --locationArray[employees[i].getRequest3()];
	 		   }else if (trySpecialList(employees[i],REQUEST_3,employees[i].getRequest3(),i)){
		  			 continue;
			   }else if(employees[i].getCurrentLocation() != -1 && locationArray[employees[i].getCurrentLocation()] > 0){
	 			   employees[i].setAssignedLocation(0); 
	 			   --locationArray[employees[i].getCurrentLocation()];
	    	   }else{
	 			   employees[i].setAssignedLocation(4);	 			 
	 		   }
	 			  
	 	   }
	 	   
	 	 
	 	 evaluateAndOutputResults(employees);  
	 	   
	    }
	
	
	private boolean backOffAtGivenRequestForAll(int employeeId  , int request ){
    	int checkReq = 0;
    	int otherRequests[] =null;
    	
    	if(request == 2){			// my request is 2 check whether I can remove req 1 from above assigned
    		int [] otherRequests1  = {1,2};
    		otherRequests = otherRequests1;
    	}else if(request == 3){		// my request is 3 check whether I can remove req 2 from above assigned
       		int [] otherRequests1  = {1,2,3};
    		otherRequests = otherRequests1;
    	}else if(request == 0){		// my request match  is 0 (current loc)  check whether I can remove req 3 from above
    		int [] otherRequests1  = {1,2,3,0};
    		otherRequests = otherRequests1;
    	}else{
    		throw new RuntimeException();
    	}
    	
    	
    		
    	for(int j =0; j < otherRequests.length ; ++j){
    		int sourceReqId  = otherRequests[j];
    	    int locationId = -1 ;
    	    
    	    if(sourceReqId == 1){
    	    	locationId = employees[employeeId].getRequest1();
    	    }else if(sourceReqId == 2){
    	    	locationId = employees[employeeId].getRequest2();
    	    }else if(sourceReqId == 3){
    	    	locationId = employees[employeeId].getRequest3();
    	    }
    	    if(locationId == LOCATION_NOT_IN_VACANCY_LIST){
    	    	continue;
    	    }
    	    
	    	for(int i =employeeId-1 ; i > 0 ; --i){
	    		if(employees[i].getAssignedLocation() == 3 && (employees[i].getRequest3() == locationId && employees[i].getCurrentLocation() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getCurrentLocation()] > 0)){
	    		    	locationArray[employees[i].getCurrentLocation()]--;
						locationArray[employees[i].getRequest3()]++;
						employees[i].setAssignedLocation(0);
						//For source employee
						employees[employeeId].setAssignedLocation(sourceReqId);
			  			--locationArray[locationId];
						return true;
				}else if(employees[i].getAssignedLocation() == 2 && (employees[i].getRequest2() == locationId) && ( employees[i].getRequest3() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getRequest3()] > 0)){ // my request is 3 check whether I can remove req 2 assigned from above and get me a location
	    			    locationArray[employees[i].getRequest3()]--;
						locationArray[employees[i].getRequest2()]++;
						employees[i].setAssignedLocation(3);
						//For source employee
						 employees[employeeId].setAssignedLocation(sourceReqId);
						 --locationArray[locationId];
						return true;					
	    		}else if(employees[i].getAssignedLocation() == 1 && (employees[i].getRequest1() == locationId) && ( employees[i].getRequest2() !=  LOCATION_NOT_IN_VACANCY_LIST && locationArray[employees[i].getRequest2()] > 0)){
	    				locationArray[employees[i].getRequest2()]--;
						locationArray[employees[i].getRequest1()]++;
						employees[i].setAssignedLocation(2);
						//For source employee
						 employees[employeeId].setAssignedLocation(sourceReqId);
			  			  --locationArray[locationId];
						return true;
				}
	    		
	    		
	    	}
    	}
    	return false;	
    }
	
	
	public boolean trySpecialList( BasicEmployee e, int requestType, int locationId, int employeeId){
		String realLocation = null ;
		if(locationId == LOCATION_NOT_IN_VACANCY_LIST){		
			switch(requestType){
			case 1:
				realLocation = eligibleEmployeeList.get(employeeId).getRequest1();
				break;
			case 2:
				realLocation = eligibleEmployeeList.get(employeeId).getRequest2();
				break;
			case 3:
				realLocation = eligibleEmployeeList.get(employeeId).getRequest3();
				break;
			default:
				throw new RuntimeException();
			}
						
		}else{
			realLocation = 	getRealLocationId(locationId);
		}
		
		System.out.println("Location "+ realLocation);
 		for (int i = 0; i < specialEmployeeList.size(); i++) {
		Employee specialEmployee = specialEmployeeList.get(i);
		String sRequest1 = specialEmployee.getRequest1();
		String sRequest2 = specialEmployee.getRequest2();
		String sRequest3 = specialEmployee.getRequest3();
		String sCurrentLocation = specialEmployee.getCurrentLocation();
		
		
		
		
		if(specialEmployee.getAssignedLocation() == NO_ASSIGNMENT && realLocation.equals(sCurrentLocation) && getLocationId(sRequest1) != -1 && getLocationId(sRequest1) != -2 &&  locationArray[getLocationId(sRequest1)] >0){
			System.out.println("Found a match for 1");
			specialEmployee.setAssignedLocation(1);
		
			locationArray[getLocationId(sRequest1)]--;
			//For source employee
			e.setAssignedLocation(requestType);
			specialLocations.reduce(realLocation);
			
  			return true;
		}else if(specialEmployee.getAssignedLocation() == NO_ASSIGNMENT && realLocation.equals(sCurrentLocation) && getLocationId(sRequest2) != -1 && getLocationId(sRequest2) != -2 && locationArray[getLocationId(sRequest2)] >0){
			System.out.println("Found a match for 2");
			locationArray[getLocationId(sRequest2)]--;
			specialEmployee.setAssignedLocation(2);
			specialLocations.reduce(realLocation);
			//For source employee
			e.setAssignedLocation(requestType);
  			return true;
		}else if(specialEmployee.getAssignedLocation() == NO_ASSIGNMENT && realLocation.equals(sCurrentLocation) && getLocationId(sRequest3) != -1 && getLocationId(sRequest3) != -2 && locationArray[getLocationId(sRequest3)] >0){
			System.out.println("Found a match for 3");
			locationArray[getLocationId(sRequest3)]--;
			specialEmployee.setAssignedLocation(3);
			specialLocations.reduce(realLocation);
			//For source employee
			e.setAssignedLocation(requestType);
  			return true;
		}
	
	  }
	return false;	
	}
	
	
	
//Utility functions	
	
	private int getLocationId(String loc){
		
		int id =0;
		//System.out.println(loc);
		if(loc.trim().equals("")){
			return -2;
		}
		for(String key : eligibleLocations.keySet()){
			if(loc.trim().equals(key.trim())){
				return id;
			}
			++id;
		}
		return -1;
	}
	
	private String getRealLocationId(int loc){
		int i = 0;
		for ( String locs: eligibleLocations.keySet()) {
			   if(i ==loc){
				   return locs;
			   }
			++i;
		}
		return "";
	}
		
private BasicEmployee normalizeUnrequestedLocatons(BasicEmployee employee){
		
		if(employee.getRequest1() !=  NO_LOCATION_REQUESTED  && employee.getRequest2() ==  NO_LOCATION_REQUESTED  && employee.getRequest3() ==  NO_LOCATION_REQUESTED ){ //R1 _ _
				employee.setRequest2(employee.getRequest1());
				employee.setRequest3(employee.getRequest1());
		}else if(employee.getRequest1() !=  NO_LOCATION_REQUESTED  && employee.getRequest2() !=  NO_LOCATION_REQUESTED  && employee.getRequest3() ==  NO_LOCATION_REQUESTED ){ //R1 R2 _
				employee.setRequest3(employee.getRequest2());
		}else if(employee.getRequest1() !=  NO_LOCATION_REQUESTED  && employee.getRequest2() ==  NO_LOCATION_REQUESTED  && employee.getRequest3() !=  NO_LOCATION_REQUESTED ){ //R1 _ R3
				employee.setRequest2(employee.getRequest1());					
		}else if(employee.getRequest1() ==  NO_LOCATION_REQUESTED  && employee.getRequest2() !=  NO_LOCATION_REQUESTED  && employee.getRequest3() ==  NO_LOCATION_REQUESTED ){ // _ R2 _
				employee.setRequest1(employee.getRequest2());
				employee.setRequest3(employee.getRequest2());
		}else if(employee.getRequest1() ==  NO_LOCATION_REQUESTED  && employee.getRequest2() !=  NO_LOCATION_REQUESTED  && employee.getRequest3() !=  NO_LOCATION_REQUESTED ){ // _ R2 R3
				employee.setRequest1(employee.getRequest2());				
		}else if(employee.getRequest1() ==  NO_LOCATION_REQUESTED  && employee.getRequest2() ==  NO_LOCATION_REQUESTED  && employee.getRequest3() !=  NO_LOCATION_REQUESTED ){ // _ _ R3
				employee.setRequest1(employee.getRequest3());
				employee.setRequest2(employee.getRequest3());
		}
	
		if(employee.getRequest1() == NO_LOCATION_REQUESTED){
			employee.setRequest1(employee.getCurrentLocation());
		}else if (employee.getRequest2() == NO_LOCATION_REQUESTED){
			employee.setRequest2(employee.getCurrentLocation());
		}else if (employee.getRequest3() == NO_LOCATION_REQUESTED){
			employee.setRequest3(employee.getCurrentLocation());
		}
		
		return employee;
	}
	
	private boolean allRequestsUnsatisfactory(int req1, int req2, int req3){
		if(!(req1 == NO_LOCATION_REQUESTED || req1 == LOCATION_NOT_IN_VACANCY_LIST)){
			return false;
		}
		if(!(req2 == NO_LOCATION_REQUESTED || req2 == LOCATION_NOT_IN_VACANCY_LIST)){
			return false;
		}
		if(!(req3 == NO_LOCATION_REQUESTED || req3 == LOCATION_NOT_IN_VACANCY_LIST)){
			return false;
		}
	return true;	
}
	
	private void evaluateAndOutputResults(BasicEmployee[] employees){
		 int request1Count =0;
	 	   int request2Count =0;
	 	   int request3Count =0;
	 	   int currenLocationCount =0;
	 	   int noLocationCount =0;
	 	  Integer[] assignmets = new Integer[employees.length];
	 	   
		 for (int i = 0; i < employees.length; i++) {
			 assignmets[i] = employees[i].getAssignedLocation();
			 
	 		   switch(employees[i].getAssignedLocation() ){	 		   
	 		   	case 1:
	 		   		request1Count++;
	 			   break;
	 		   	case 2:
	 		   		request2Count++;
	 			   break;
	 		   	case 3:
	 		   		request3Count++;
	 				break;
	 		   	case 0:
	 		   		currenLocationCount++;
	 		   	 
	 				break;	   
	 		   	case 4:
	 		   		noLocationCount++;
	 		   	 System.out.println("Employee id : "+employees[i].getEmployeeId()+" "+ employees[i].getRequest1()+" "+employees[i].getRequest2() + " "+ employees[i].getRequest3());
	 		   		break;
	 				
	 		   }
	 		  
	 	   }
	 	   
		 int remainingLocations =0;
		 for (int i = 0; i < locationArray.length; i++) {
			remainingLocations += locationArray[i];
		}
	 	   
	 	   
		 int weight =getWeightedEstimation(assignmets);
	 	

		 System.out.println("Number of eligible employees "+ eligibleEmployeeList.size());
		 System.out.println("Number of special employees "+ specialEmployeeList.size());
	 	 System.out.println("Request 1 count: "+ request1Count);
	 	 System.out.println("Request 2 count: "+ request2Count);
	 	 System.out.println("Request 3 count: "+ request3Count);
	 	 System.out.println("Current Location count: "+ currenLocationCount);
	 	 System.out.println("No Location count: "+ noLocationCount);
	 	 System.out.println("Weight is : "+ weight);
	     System.out.println("Not considered employees no:  "+  noRequestEmployees.size());
	 	 System.out.println("Remaining Locations : "+ remainingLocations);
	 	 System.out.println("No request and +5 employees : "+ moreThan5AndNoRequestEmployees.size() );
	}

private int getWeightedEstimation(Integer[] assignments){ 
		int count =0;
		
		for (Integer assignment : assignments) {
			switch(assignment){
			case 1: //Req 1
				count += 9;
				break;
			case 2: //Req 2
				count += 5;
				break;
			case 3: //Req 2
				count += 3;
				break;
			case 0: //Current location
				count += 1;
				break;
			 case 4://Current location
				count += 0;
				break;	
			}
		}
		
		return count;
}

private void weightSpecialList(){
	
	int request1Count =0;
	   int request2Count =0;
	   int request3Count =0;
	   int currenLocationCount =0;
	   int noLocationCount =0;
	   int remainingLocationCount =0;
	   Integer[] assignmets = new Integer[specialEmployeeList.size()];
	for (int i = 0; i < specialEmployeeList.size(); i++) {
		assignmets[i] = specialEmployeeList.get(i).getAssignedLocation();
		 switch(specialEmployeeList.get(i).getAssignedLocation() ){	 		   
		   	case 1:
		   		request1Count++;
			   break;
		   	case 2:
		   		request2Count++;
			   break;
		   	case 3:
		   		request3Count++;
				break;
		   	case 0:
		   		currenLocationCount++;		   	 
				break;	   
		   	case 4:
		   		noLocationCount++;
		   	// System.out.println("Employee id : "+employees[i].getEmployeeId()+" "+ employees[i].getRequest1()+" "+employees[i].getRequest2() + " "+ employees[i].getRequest3());
		   		break;
		   	default:
		   		//throw new RuntimeException();				
		   }
		 
		 }
	
	for (String loc : specialLocations.keySet()) {
		
		remainingLocationCount += specialLocations.get(loc);
	}
	 int weight =getWeightedEstimation(assignmets);
	   System.out.println("Special list : Request 1 count: "+ request1Count);
 	   System.out.println("Special list : Request 2 count: "+ request2Count);
 	   System.out.println("Special list : Request 3 count: "+ request3Count);
 	   System.out.println("Special list : Current Location count: "+ currenLocationCount);
 	   System.out.println("Special list : No Location count: "+ noLocationCount);
 	   System.out.println("Special list : Weight is : "+ weight);
 	   System.out.println("Special list : Remaining locations count: "+ remainingLocationCount);
		
}
	
public void distributeLocationsOfSpecialListInNaiveWay(){
	for (int i = 0; i < specialEmployeeList.size(); i++) {
		Employee e =specialEmployeeList.get(i);
	    if( e.getAssignedLocation() == 9 ){
		if(!e.getRequest1().equals("") &&  specialLocations.get(e.getRequest1()) != null && specialLocations.get(e.getRequest1()) > 0){
	    	   specialLocations.reduce(e.getRequest1());
	    	   e.setAssignedLocation(REQUEST_1);
		   }else if(!e.getRequest2().equals("") && specialLocations.get(e.getRequest2()) != null && specialLocations.get(e.getRequest2()) > 0){
			   specialLocations.reduce(e.getRequest2());
	    	   e.setAssignedLocation(REQUEST_2);
		   }else if(!e.getRequest3().equals("") && specialLocations.get(e.getRequest3()) != null && specialLocations.get(e.getRequest3()) > 0){
			   specialLocations.reduce(e.getRequest3());
	    	   e.setAssignedLocation(REQUEST_3);
		   }else if(!e.getCurrentLocation().equals("") && specialLocations.get(e.getCurrentLocation()) != null && specialLocations.get(e.getCurrentLocation()) > 0){
			   specialLocations.reduce(e.getCurrentLocation());
	    	   e.setAssignedLocation(CURRENT_LOCATION);
		   }else{
			   e.setAssignedLocation(4);
		  }
	    }
	 
	// evaluateAndOutputResults(employees);  
	   
	}
	
}	
	
public void algorithmMaximumRequest1(){
	
	int count =0;
	for (int i = 0; i < employees.length; i++) {	
		boolean found = false;
		BasicEmployee employee = employees[i];
	for (int j = 0; j < locationArray.length; j++) {			
			
			if(employee.getRequest1()== LOCATION_NOT_IN_VACANCY_LIST ){

				break;
			}else if(employee.getRequest1()!= LOCATION_NOT_IN_VACANCY_LIST && employee.getRequest1() == j && locationArray[j] > 0 && employee.getAssignedLocation() == 9){
				employee.setAssignedLocation(REQUEST_1);
				locationArray[j] = locationArray[j] -1;	
				found = true;
				System.out.println("In algo "+ employee.getRequest1() + " "+locationArray[j]);
			break;
			}
		}
		if((employee.getAssignedLocation() == NO_ASSIGNMENT) && !found){
			trySpecialList(employees[i],REQUEST_1,employees[i].getRequest1(),i);
		}
	}

	for (int i = 0; i < employees.length; i++) {
		boolean found = false;
		BasicEmployee employee = employees[i];
		for (int j = 0; j < locationArray.length; j++) {	
		
			
			if(employee.getRequest2()!= LOCATION_NOT_IN_VACANCY_LIST && employee.getRequest2() == j && locationArray[j] > 0 && employee.getAssignedLocation() == 9){
				employee.setAssignedLocation(2);
				locationArray[j]--;
				found = true;
				break;
			}
		
		}
		if((employee.getAssignedLocation() == NO_ASSIGNMENT) && !found){
			trySpecialList(employees[i],REQUEST_2,employees[i].getRequest2(),i);
		}
		
//	System.out.println("Location "+i+" "+ locationArray[i] );
	}
	
	
	for (int i = 0; i < employees.length; i++) {
		boolean found = false;
		BasicEmployee employee = employees[i];
		for (int j = 0; j < locationArray.length; j++) {	
			
			if(employee.getRequest3()!= LOCATION_NOT_IN_VACANCY_LIST && employee.getRequest3() == j && locationArray[j] > 0 && employee.getAssignedLocation() == 9){
				employee.setAssignedLocation(3);
				locationArray[j]--;
				found = true;
				break;
			}
		}
		
		if((employee.getRequest3() == NO_ASSIGNMENT) && !found){
			trySpecialList(employees[i],REQUEST_3,employees[i].getRequest3(),i);
		}
	}
	
	for (int j = 0; j < employees.length; j++) {	
	for (int i = 0; i < locationArray.length; i++) {	
		BasicEmployee employee = employees[j];
			if(employee.getCurrentLocation()!= LOCATION_NOT_IN_VACANCY_LIST && employee.getCurrentLocation() == i && locationArray[i] > 0 && employee.getAssignedLocation() == 9){
				employee.setAssignedLocation(0);
				locationArray[i]--;
				break;
			}
			
			/*if(locationArray[i] ==0){
				break;
			}*/
		}
	}

	for (int j = 0; j < employees.length; j++) {
		
		BasicEmployee employee = employees[j];
		if(employee.getAssignedLocation() == 9){
			employee.setAssignedLocation(4);
			
		}
	}
	
	evaluateAndOutputResults(employees);  	
}
	
	
public   class CountingHashMap extends HashMap<String, Integer> {		
		
	    public Integer add(String key) {
	    	if(this.containsKey(key)){
		        int currentCount = get(key);
		        currentCount++;
		        this.put(key, currentCount);
	        return currentCount;  
	    	}else{
	    		this.put(key, 1);
	    		return 1;  
	    	}
	     
	    }
	    
	    public Integer reduce(String key) {
	        int currentCount = get(key);
		        if(currentCount == 1){
		        		// currentCount--;
		        		super.remove(key);
		        }else if(currentCount > 1){
		        	currentCount--;
		        	super.put(key, currentCount);
		        }
	        return currentCount;    
	    }
	    
	    public Integer reduceWithoutRemoval(String key) {
	        int currentCount = get(key);
		        if(currentCount == 0){
		        		// currentCount--;
		        	super.put(key, 0);
		        }else if(currentCount > 0){
		        	currentCount--;
		        	super.put(key, currentCount);
		        }
	        return currentCount;    
	    }
  }
}
